
/*******************************************************************************
 * Copyleft (c) 2021 Kcode
 *
 * @file    iis.c
 * @brief   iis芯片的相关硬件操作与初始化
 * @author  K
 * @version 0.0.1
 * @date    2021-08-05
 * @license MulanPSL-1.0
 *
 * 文件修改历史：
 * <时间>       | <版本>    | <作者>  | <描述>
 * 2021-08-05   | v0.0.1    | Kcode   | iis芯片的相关硬件操作与初始化
 * -----------------------------------------------------------------------------
 ******************************************************************************/

#include "s3c24xx.h"

/*!
 * IIS芯片涉及的寄存器
 */
#define IISCON              (*(volatile unsigned long *)0x55000000)
#define IISMOD              (*(volatile unsigned long *)0x55000004)
#define IISPSR              (*(volatile unsigned long *)0x55000008)
#define IISFCON             (*(volatile unsigned long *)0x5500000C)
#define IISFIFO             (*(volatile unsigned long *)0x55000010)

#define PCLK 50000000   /**< 系统使用的PCLK */

#define ABS(a, b) ((a > b) ? (a - b) : (b - a))   /**< 计算两数差值的绝对值 */

/*!
 * @brief  对iis芯片进行初始化
 * @param[in] bits_per_sample 视频数据的每位采样需要的bit数
 * @param[in] fs 视频数据的采样率
 * @return void
 */
void iis_init(int bits_per_sample, int fs)
{   
    int i;
    int pre;
    int min;
    int tmp_fs;

    /*!
     * 配置GPIO用于IIS 
     */
    GPECON &= ~((3 << 0) | (3 << 2) | (3 << 4) | (3 << 6) | (3 << 8));
    GPECON |= ((2 << 0) | (2 << 2) | (2 << 4) | (2 << 6) | (2 << 8));
    
    /*! 
     * IISMOD: IIS模式寄存器
     *  bit[9]   : Master clock select, 0-PCLK，默认
     *  bit[8]   : 0 = Master mode(主动模式)，默认
     *  bit[7:6] : 10 = Transmit mode(发送模式)
     *  bit[5]   : 声道极性，使用默认，不设置
     *  bit[4]   : 0-IIS compatible format (Left)-justified format(兼容codec芯片的格式)
     *  bit[3]   : 每位采样需要的bit数，0 = 8bit，1 = 16bit
     *  bit[2]   : 384fs, 确定了MASTER CLOCK之后, fs = MASTER CLOCK/384
     *  bit[1:0] : Serial bit clock frequency select, 32fs
     */
    if (bits_per_sample == 8)
    {
        IISMOD = (2 << 6) | (0 << 4) | (0 << 3) | (1 << 2) | (1 << 0);
    }
    else
    {
        IISMOD = (2 << 6) | (0 << 4) | (1 << 3) | (1 << 2) | (1 << 0);
    }    

    /*!
     * IISPSR: IIS分频寄存器
     *  Master clock = PCLK/(n+1)
     *  fs = Master clock / 384
     *  fs = PCLK / (n+1) / 384
     */
    pre = 0;
    min  = 0xffff;
    for (i = 0; i < 31; i++)
    {
        /* 计算临时采样率 */
        tmp_fs = PCLK / 384 / (i + 1);

        /* 得到使采样率误差最小的分频数 */
        if (ABS(tmp_fs, fs) < min)
        {
            min = ABS(tmp_fs, fs);
            pre = i;
        }
    }
    IISPSR = (pre << 5) | (pre << 0);

    /*! 
     * IISFCON: IIS FIFO接口寄存器
     *  bit[15] : Transmit FIFO access mode select, 1-DMA
     *  bit[13] : Transmit FIFO, 1-enable
     */
    IISFCON = (1 << 15) | (1 << 13);
     
    /*!
     * IISCON: IIS控制寄存器
     *  bit[5] : Transmit DMA service request, 1-enable
     *  bit[1] : IIS prescaler, 1-enable
     */
    IISCON = (1 << 5) | (1 << 1);
}

/*!
 * @brief  iis传输启动
 * @return void
 */
void iis_start(void)
{
    IISCON |= (1 << 0);
}

/*!
 * @brief  iis传输停止
 * @return void
 */
void iis_stop(void)
{
    IISCON &= ~(1 << 0);
}
